home *** CD-ROM | disk | FTP | other *** search
Wrap
/***************************************************************************** IsoHex18_3.cpp Ernest S. Pazera 09SEPT2000 Start a WIN32 Application Workspace, add in this file Requires the following libs: ddraw.lib, dxguid.lib Requires the following files: DDFuncs.h.cpp, GDICanvas.h/cpp, IsoMouseMap.h/cpp, IsoScroller.h/cpp, IsoTilePlotter.h/cpp, IsoTileWalker.h/cpp TileSet.h/cpp. IsoHexCore.h, IsoHexDefs.h IsoRenderer.h/cpp *****************************************************************************/ ////////////////////////////////////////////////////////////////////////////// //INCLUDES ////////////////////////////////////////////////////////////////////////////// #define WIN32_LEAN_AND_MEAN #include <windows.h> #include "DDFuncs.h" #include "TileSet.h" #include "IsoHexCore.h" #include "IsoRenderer.h" #include <list> ////////////////////////////////////////////////////////////////////////////// //DEFINES ////////////////////////////////////////////////////////////////////////////// //name for our window class #define WINDOWCLASS "ISOHEX18" //title of the application #define WINDOWTITLE "IsoHex 18-3" const int MAPWIDTH=40; const int MAPHEIGHT=40; //gamestates const int GS_IDLE=0;//waits for a keypress const int GS_STARTTURN=1;//starts a players turn const int GS_ENDTURN=2;//ends a players turn const int GS_NEXTUNIT=3;//finds the next unit to move const int GS_STARTMOVE=4;//starts moving the unit const int GS_DOMOVE=5;//moves the unit const int GS_ENDMOVE=6;//ends a unit move const int GS_NULLMOVE=7;//tells a unit to not move const int GS_SKIPMOVE=8;//temporarily skip the move ////////////////////////////////////////////////////////////////////////////// //TYPEDEFS/STRUCTS ////////////////////////////////////////////////////////////////////////////// struct UnitInfo//unit information structure { int iType;//type of unit int iTeam;//team to which the unit belongs POINT ptPosition;//map location of the unit int iMovePoints;//number of movepoints left this turn }; typedef UnitInfo *PUNITINFO;//pointer type alias for unitinfo typedef std::list<PUNITINFO> UNITLIST;//list of units typedef std::list<PUNITINFO>::iterator UNITLISTITER;//iterator for unit list ////////////////////////////////////////////////////////////////////////////// //PROTOTYPES ////////////////////////////////////////////////////////////////////////////// bool Prog_Init();//game data initalizer void Prog_Loop();//main game loop void Prog_Done();//game clean up ////////////////////////////////////////////////////////////////////////////// //GLOBALS ////////////////////////////////////////////////////////////////////////////// HINSTANCE hInstMain=NULL;//main application handle HWND hWndMain=NULL;//handle to our main window //game state int iGameState=GS_IDLE; int iCurrentTeam=0;//the team whose turn it currently is //directdraw LPDIRECTDRAW7 lpdd=NULL; LPDIRECTDRAWSURFACE7 lpddsMain=NULL; LPDIRECTDRAWSURFACE7 lpddsBack=NULL; LPDIRECTDRAWSURFACE7 lpddsFrame=NULL; //tilesets CTileSet tsBack;//background CTileSet tsUnit;//unit CTileSet tsShield;//shields //offsets for the shields POINT ptShieldOffset[2];//one for each unit //isohexcore components CTilePlotter TilePlotter;//plotter CTileWalker TileWalker;//walker CScroller Scroller;//scroller CMouseMap MouseMap;//mousemap CRenderer Renderer;//renderer POINT ptScroll;//keep track of how quickly we scroll //map location structure struct MapLocation { UNITLIST ulUnitList;//list of units on this map location }; MapLocation mlMap[MAPWIDTH][MAPHEIGHT];//map array UNITLIST MainUnitList;//unit list for all units UNITLIST TeamUnitList;//unit list for teams(Current Players Turn) PUNITINFO pCurrentUnit;//current unit being moved bool bFlash;//controls the flashing of the current unit ISODIRECTION idMoveUnit;//direction in which the unit will be moved //rendering functionprototype void RenderFunc(LPDIRECTDRAWSURFACE7 lpddsDst,RECT* rcClip,int xDst,int yDst,int xMap,int yMap); ////////////////////////////////////////////////////////////////////////////// //WINDOWPROC ////////////////////////////////////////////////////////////////////////////// LRESULT CALLBACK TheWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { //which message did we get? switch(uMsg) { case WM_KEYDOWN: { switch(wParam) { case VK_ESCAPE: { DestroyWindow(hWndMain); return(0); }break; case VK_SPACE://do not move unit { if(iGameState==GS_IDLE) iGameState=GS_NULLMOVE;//only respond when gamestate is GS_IDLE; return(0); }break; case 'W'://wait to move this unit later { if(iGameState==GS_IDLE) iGameState=GS_SKIPMOVE;//skip this unit for now }break; case VK_NUMPAD8: case VK_UP: { if(iGameState==GS_IDLE)//gamestate must be GS_IDLE { idMoveUnit=ISO_NORTH;//move to the north POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking { if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty { iGameState=GS_STARTMOVE;//set the unit in motion } else { UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list PUNITINFO pUnitInfo=*iter;//get the unit from the list if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team { iGameState=GS_STARTMOVE; } } } } }break; case VK_NUMPAD9: case VK_PRIOR: { if(iGameState==GS_IDLE)//gamestate must be GS_IDLE { idMoveUnit=ISO_NORTHEAST;//move to the north POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking { if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty { iGameState=GS_STARTMOVE;//set the unit in motion } else { UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list PUNITINFO pUnitInfo=*iter;//get the unit from the list if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team { iGameState=GS_STARTMOVE; } } } } }break; case VK_NUMPAD6: case VK_RIGHT: { if(iGameState==GS_IDLE)//gamestate must be GS_IDLE { idMoveUnit=ISO_EAST;//move to the north POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking { if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty { iGameState=GS_STARTMOVE;//set the unit in motion } else { UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list PUNITINFO pUnitInfo=*iter;//get the unit from the list if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team { iGameState=GS_STARTMOVE; } } } } }break; case VK_NUMPAD3: case VK_NEXT: { if(iGameState==GS_IDLE)//gamestate must be GS_IDLE { idMoveUnit=ISO_SOUTHEAST;//move to the north POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking { if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty { iGameState=GS_STARTMOVE;//set the unit in motion } else { UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list PUNITINFO pUnitInfo=*iter;//get the unit from the list if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team { iGameState=GS_STARTMOVE; } } } } }break; case VK_NUMPAD2: case VK_DOWN: { if(iGameState==GS_IDLE)//gamestate must be GS_IDLE { idMoveUnit=ISO_SOUTH;//move to the north POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking { if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty { iGameState=GS_STARTMOVE;//set the unit in motion } else { UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list PUNITINFO pUnitInfo=*iter;//get the unit from the list if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team { iGameState=GS_STARTMOVE; } } } } }break; case VK_NUMPAD1: case VK_END: { if(iGameState==GS_IDLE)//gamestate must be GS_IDLE { idMoveUnit=ISO_SOUTHWEST;//move to the north POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking { if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty { iGameState=GS_STARTMOVE;//set the unit in motion } else { UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list PUNITINFO pUnitInfo=*iter;//get the unit from the list if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team { iGameState=GS_STARTMOVE; } } } } }break; case VK_NUMPAD4: case VK_LEFT: { if(iGameState==GS_IDLE)//gamestate must be GS_IDLE { idMoveUnit=ISO_WEST;//move to the north POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking { if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty { iGameState=GS_STARTMOVE;//set the unit in motion } else { UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list PUNITINFO pUnitInfo=*iter;//get the unit from the list if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team { iGameState=GS_STARTMOVE; } } } } }break; case VK_NUMPAD7: case VK_HOME: { if(iGameState==GS_IDLE)//gamestate must be GS_IDLE { idMoveUnit=ISO_NORTHWEST;//move to the north POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking { if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty { iGameState=GS_STARTMOVE;//set the unit in motion } else { UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list PUNITINFO pUnitInfo=*iter;//get the unit from the list if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team { iGameState=GS_STARTMOVE; } } } } }break; } }break; case WM_DESTROY://the window is being destroyed { //tell the application we are quitting PostQuitMessage(0); //handled message, so return 0 return(0); }break; case WM_PAINT://the window needs repainting { //a variable needed for painting information PAINTSTRUCT ps; //start painting HDC hdc=BeginPaint(hwnd,&ps); ///////////////////////////// //painting code would go here ///////////////////////////// //end painting EndPaint(hwnd,&ps); //handled message, so return 0 return(0); }break; } //pass along any other message to default message handler return(DefWindowProc(hwnd,uMsg,wParam,lParam)); } ////////////////////////////////////////////////////////////////////////////// //WINMAIN ////////////////////////////////////////////////////////////////////////////// int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) { //assign instance to global variable hInstMain=hInstance; //create window class WNDCLASSEX wcx; //set the size of the structure wcx.cbSize=sizeof(WNDCLASSEX); //class style wcx.style=CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; //window procedure wcx.lpfnWndProc=TheWindowProc; //class extra wcx.cbClsExtra=0; //window extra wcx.cbWndExtra=0; //application handle wcx.hInstance=hInstMain; //icon wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION); //cursor wcx.hCursor=LoadCursor(NULL,IDC_ARROW); //background color wcx.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); //menu wcx.lpszMenuName=NULL; //class name wcx.lpszClassName=WINDOWCLASS; //small icon wcx.hIconSm=NULL; //register the window class, return 0 if not successful if(!RegisterClassEx(&wcx)) return(0); //create main window hWndMain=CreateWindowEx(0,WINDOWCLASS,WINDOWTITLE, WS_POPUP | WS_VISIBLE,0,0,320,240,NULL,NULL,hInstMain,NULL); //error check if(!hWndMain) return(0); //if program initialization failed, then return with 0 if(!Prog_Init()) return(0); //message structure MSG msg; //message pump for(;;) { //look for a message if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { //there is a message //check that we arent quitting if(msg.message==WM_QUIT) break; //translate message TranslateMessage(&msg); //dispatch message DispatchMessage(&msg); } //run main game loop Prog_Loop(); } //clean up program data Prog_Done(); //return the wparam from the WM_QUIT message return(msg.wParam); } ////////////////////////////////////////////////////////////////////////////// //INITIALIZATION ////////////////////////////////////////////////////////////////////////////// bool Prog_Init() { //create IDirectDraw object lpdd=LPDD_Create(hWndMain,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT); //set display mode lpdd->SetDisplayMode(640,480,16,0,0); //create primary surface lpddsMain=LPDDS_CreatePrimary(lpdd,1); //get back buffer lpddsBack=LPDDS_GetSecondary(lpddsMain); //create the frame buffer lpddsFrame=LPDDS_CreateOffscreen(lpdd,640,480); //load in the mousemap MouseMap.Load("MouseMap.bmp"); //set up the tile plotter TilePlotter.SetMapType(ISOMAP_DIAMOND);//diamond mode TilePlotter.SetTileSize(MouseMap.GetWidth(),MouseMap.GetHeight());//grab width and height from mousemap //set up tile walker to diamond mode TileWalker.SetMapType(ISOMAP_DIAMOND); //set up screeen space RECT rcTemp; SetRect(&rcTemp,0,0,640,480); Scroller.SetScreenSpace(&rcTemp); //load in tiles and cursor tsBack.Load(lpdd,"backgroundts.bmp"); tsUnit.Load(lpdd,"units.bmp"); tsShield.Load(lpdd,"shields.bmp"); //calculate the shield offsets ptShieldOffset[0].x=tsUnit.GetTileList()[0].rcSrc.right-tsUnit.GetTileList()[0].ptAnchor.x; ptShieldOffset[0].y=tsUnit.GetTileList()[0].rcSrc.top-tsUnit.GetTileList()[0].ptAnchor.y; ptShieldOffset[1].x=tsUnit.GetTileList()[1].rcSrc.right-tsUnit.GetTileList()[1].ptAnchor.x; ptShieldOffset[1].y=tsUnit.GetTileList()[1].rcSrc.top-tsUnit.GetTileList()[1].ptAnchor.y; //grab tile extent from tileset CopyRect(&rcTemp,&tsBack.GetTileList()[0].rcDstExt); //calculate the worldspace Scroller.CalcWorldSpace(&TilePlotter,&rcTemp,MAPWIDTH,MAPHEIGHT); //calculate the mousemap reference point MouseMap.CalcReferencePoint(&TilePlotter,&rcTemp); //calculate anchor space Scroller.CalcAnchorSpace(); //set wrap modes for scroller Scroller.SetHWrapMode(WRAPMODE_CLIP); Scroller.SetVWrapMode(WRAPMODE_CLIP); //set scroller anchor to (0,0) Scroller.GetAnchor()->x=0; Scroller.GetAnchor()->y=0; //attach scrolelr and tilewalker to mousemap MouseMap.SetScroller(&Scroller); MouseMap.SetTileWalker(&TileWalker); //set up the map to a random tilefield int x; int y; for(x=0;x<MAPWIDTH;x++) { for(y=0;y<MAPHEIGHT;y++) { mlMap[x][y].ulUnitList.clear();//clear out the list for this map location } } //place the units int team; int count; PUNITINFO pUnitInfo; POINT ptTest; for(team=0;team<2;team++)//place units for both teams { for(count=0;count<20;count++)//place 20 units for each team { //check for a valid placement bool found=false; while(!found) { //random placement ptTest.x=rand()%MAPWIDTH; ptTest.y=rand()%MAPHEIGHT; //check for a unit at that position if(mlMap[ptTest.x][ptTest.y].ulUnitList.empty()) { //unit list at location is empty... you can place the unit found=true; } else { //unit list is not empty, so must be occupied by the same team to be a valid location UNITLISTITER iter=mlMap[ptTest.x][ptTest.y].ulUnitList.begin();//get iterator to beginning of list pUnitInfo=*iter;//grab the items stored //check for the same team if(pUnitInfo->iTeam==team) { //same team, valid location found=true; } } } //create the unit pUnitInfo=new UnitInfo; pUnitInfo->iTeam=team;//team pUnitInfo->iType=rand()%2;//type pUnitInfo->ptPosition=ptTest;//location //place unit in the main list MainUnitList.push_back(pUnitInfo); //place unit on the map mlMap[pUnitInfo->ptPosition.x][pUnitInfo->ptPosition.y].ulUnitList.push_back(pUnitInfo); } } //calculate the extent rect RECT rcExtent; CopyRect(&rcExtent,&tsBack.GetTileList()[0].rcDstExt);//set to background extent UnionRect(&rcExtent,&rcExtent,&tsUnit.GetTileList()[0].rcDstExt);//union with unit extent rcExtent.right+=tsShield.GetTileList()[0].rcDstExt.right;//adjust the extent for the width of the shield //set up the renderer Renderer.SetBackBuffer(lpddsBack); Renderer.SetExtentRect(&rcExtent); Renderer.SetFrameBuffer(lpddsFrame); Renderer.SetMapSize(MAPWIDTH,MAPHEIGHT); Renderer.SetMouseMap(&MouseMap); Renderer.SetPlotter(&TilePlotter); Renderer.SetRenderFunction(RenderFunc); Renderer.SetScroller(&Scroller); Renderer.SetUpdateRectCount(100); Renderer.SetWalker(&TileWalker); //set the initial gamestate iGameState=GS_STARTTURN; iCurrentTeam=0;//current team TeamUnitList.clear();//clear out the team's unit list //update the entire screenspace Renderer.AddRect(Scroller.GetScreenSpace()); return(true);//return success } ////////////////////////////////////////////////////////////////////////////// //CLEANUP ////////////////////////////////////////////////////////////////////////////// void Prog_Done() { //release frame buffer LPDDS_Release(&lpddsFrame); //release main/back surfaces LPDDS_Release(&lpddsMain); //release directdraw LPDD_Release(&lpdd); } ////////////////////////////////////////////////////////////////////////////// //MAIN GAME LOOP ////////////////////////////////////////////////////////////////////////////// void Prog_Loop() { switch(iGameState) { case GS_STARTTURN://start the current team's turn { PUNITINFO pUnitInfo;//variable to check for the team's units UNITLISTITER iter;//iterator for the main unit list for(iter=MainUnitList.begin();iter!=MainUnitList.end();iter++)//iterate through the main unit list { pUnitInfo=*iter;//grab the unit from the list if(pUnitInfo->iTeam==iCurrentTeam)//does this unit belong to the current team? { //add this unit to the team list TeamUnitList.push_back(pUnitInfo); } } //set the next gamestate iGameState=GS_NEXTUNIT; }break; case GS_NEXTUNIT://select the next unit as the current unit { //set current unit to NULL pCurrentUnit=NULL; if(TeamUnitList.empty())//if the team unit list is empty { iGameState=GS_ENDTURN;//end the turn } else { //turn is not over UNITLISTITER iter=TeamUnitList.begin();//get the first unit in the team list pCurrentUnit=*iter;//grab the unit from the list TeamUnitList.pop_front();//remove the unit from the list mlMap[pCurrentUnit->ptPosition.x][pCurrentUnit->ptPosition.y].ulUnitList.remove(pCurrentUnit);//remove the unit from the map location mlMap[pCurrentUnit->ptPosition.x][pCurrentUnit->ptPosition.y].ulUnitList.push_front(pCurrentUnit);//place unit at the top of the map locations unit list POINT ptPlot=TilePlotter.PlotTile(pCurrentUnit->ptPosition);//plot the unit's location POINT ptScreen=Scroller.WorldToScreen(ptPlot);//translate into screen coordinates if(!PtInRect(Scroller.GetScreenSpace(),ptScreen))//check to see if point is within screenspace { //not on screen ptPlot.x-=(Scroller.GetScreenSpaceWidth()/2); ptPlot.y-=(Scroller.GetAnchorSpaceHeight()/2); //set the anchor Scroller.SetAnchor(&ptPlot); Renderer.AddRect(Scroller.GetScreenSpace()); } iGameState=GS_IDLE;//set to idling gamestate } }break; case GS_ENDTURN://end of a player's turn { //clear out team unit list(just to be sure) TeamUnitList.clear(); //change team iCurrentTeam=1-iCurrentTeam; iGameState=GS_STARTTURN;//set gamestate to start next turn }break; case GS_NULLMOVE://do not move the current unit { //don't really do anything, just go to the next unit pCurrentUnit=NULL; iGameState=GS_NEXTUNIT; }break; case GS_SKIPMOVE://skip this unit for now { //put unit at end of team unit list TeamUnitList.push_back(pCurrentUnit); pCurrentUnit=NULL;//set current unit to NULL iGameState=GS_NEXTUNIT;//select the next unit }break; case GS_STARTMOVE: { //remove the unit from the map location mlMap[pCurrentUnit->ptPosition.x][pCurrentUnit->ptPosition.y].ulUnitList.remove(pCurrentUnit); Renderer.AddTile(pCurrentUnit->ptPosition.x,pCurrentUnit->ptPosition.y); //set next gamestate iGameState=GS_DOMOVE; }break; case GS_DOMOVE: { //move the unit pCurrentUnit->ptPosition=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit); //set next gamestate iGameState=GS_ENDMOVE; }break; case GS_ENDMOVE: { //place the unit on its new map location mlMap[pCurrentUnit->ptPosition.x][pCurrentUnit->ptPosition.y].ulUnitList.push_front(pCurrentUnit); Renderer.AddTile(pCurrentUnit->ptPosition.x,pCurrentUnit->ptPosition.y); pCurrentUnit=NULL; bFlash=true; //set next gamestate iGameState=GS_NEXTUNIT; DWORD dwTimeStart=GetTickCount();//get the frame start time //scroll the frame (0,0) Renderer.ScrollFrame(0,0); //update the frame Renderer.UpdateFrame(); //flip to show the back buffer lpddsMain->Flip(0,DDFLIP_WAIT); //wait until 500 ms have passed while(GetTickCount()-dwTimeStart<500); }break; case GS_IDLE://the game is idling, update the frame, but thats about it. { DWORD dwTimeStart=GetTickCount();//get the frame start time //scroll the frame (0,0) Renderer.ScrollFrame(0,0); //toggle unit flash bFlash=!bFlash; //add the tile in which the current unit lives Renderer.AddTile(pCurrentUnit->ptPosition.x,pCurrentUnit->ptPosition.y); //update the frame Renderer.UpdateFrame(); //flip to show the back buffer lpddsMain->Flip(0,DDFLIP_WAIT); //wait until 200 ms have passed while(GetTickCount()-dwTimeStart<200); }break; } } void RenderFunc(LPDIRECTDRAWSURFACE7 lpddsDst,RECT* rcClip,int xDst,int yDst,int xMap,int yMap) { //put background tile tsBack.ClipTile(lpddsDst,rcClip,xDst,yDst,0); //check for an empty list if(!mlMap[xMap][yMap].ulUnitList.empty()) { //list is not empty UNITLISTITER iter=mlMap[xMap][yMap].ulUnitList.begin();//get iterator to beginning of list PUNITINFO pUnitInfo=*iter;//grab the item //if this is the current unit if(pUnitInfo==pCurrentUnit) { //this is the current unit if(!bFlash) return;//if flash is "off" dont render } tsUnit.ClipTile(lpddsDst,rcClip,xDst,yDst,pUnitInfo->iType);//place the unit iter++;//move to the next item in the list if(iter==mlMap[xMap][yMap].ulUnitList.end())//if the end of the list, this is a single unit { tsShield.ClipTile(lpddsDst,rcClip,xDst+ptShieldOffset[pUnitInfo->iType].x,yDst+ptShieldOffset[pUnitInfo->iType].y,pUnitInfo->iTeam*2);//place the shield } else//more than one unit... this is a stack { tsShield.ClipTile(lpddsDst,rcClip,xDst+ptShieldOffset[pUnitInfo->iType].x,yDst+ptShieldOffset[pUnitInfo->iType].y,pUnitInfo->iTeam*2+1);//place the shield } } }